package com.csp.session.impl;

import com.csp.resulthandle.BaseTypeHandle;
import com.csp.resulthandle.ListHandle;
import com.csp.resulthandle.SetHandle;
import com.csp.session.ConnectionInstance;
import com.csp.session.ExecuteMsg;
import com.csp.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 默认的sqlsession
 * @author:chengsp
 * @createTime:2019/8/22 13:10
 */
public class DefaultSqlSession implements SqlSession {
    private final static Logger logger = LoggerFactory.getLogger(DefaultSqlSession.class);
    private Connection connection;
    private ResourceWrap resourceWrap;

    public DefaultSqlSession() {
        this.connection = getConnection();
        resourceWrap = new ResourceWrap();
    }

    @Override
    public <T> T selectOne(String sql, ExecuteMsg executeMsg) {
        return ((T) selectList(sql, executeMsg).get(0));
    }

    @Override
    public <T> List<T> selectList(String sql, ExecuteMsg executeMsg) {
        String preparedSql = executeMsg.getMethodMapping().getPreparedSql();
        return (List<T>) ListHandle.getInstance().execute(getStatement(preparedSql), executeMsg, resourceWrap);
    }

    private PreparedStatement getStatement(String preparedSql) {
        try {
            return connection.prepareStatement(preparedSql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <T> Set<T> selectSet(String sql, ExecuteMsg executeMsg) {
        String preparedSql = executeMsg.getMethodMapping().getPreparedSql();
        return (Set<T>) SetHandle.getInstance().execute(getStatement(preparedSql), executeMsg, resourceWrap);
    }

    @Override
    public <K, V> Map<K, V> selectMap(String sql, ExecuteMsg executeMsg) {
        return (Map<K, V>) selectMapList(sql,executeMsg).get(0);
    }

    @Override
    public <K, V> List<Map<K, V>> selectMapList(String sql, ExecuteMsg executeMsg) {
        return selectList(sql,executeMsg);
    }

    @Override
    public <K, V> Set<Map<K, V>> selectMapSet(String sql, ExecuteMsg executeMsg) {
        return selectSet(sql,executeMsg);
    }

    @Override
    public int insert(String sql, ExecuteMsg executeMsg) {
        String preparedSql = executeMsg.getMethodMapping().getPreparedSql();
        return (int) BaseTypeHandle.getInstance().execute(getStatement(preparedSql), executeMsg, resourceWrap);
    }

    @Override
    public int update(String sql, ExecuteMsg executeMsg) {
        String preparedSql = executeMsg.getMethodMapping().getPreparedSql();
        return (int) BaseTypeHandle.getInstance().execute(getStatement(preparedSql), executeMsg, resourceWrap);
    }

    @Override
    public int delete(String sql, ExecuteMsg executeMsg) {
        String preparedSql = executeMsg.getMethodMapping().getPreparedSql();
        return (int) BaseTypeHandle.getInstance().execute(getStatement(preparedSql), executeMsg, resourceWrap);
    }

    @Override
    public void close() {
        resourceWrap.closeAll();
    }

    @Override
    public void startTransaction() {
        try {
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void commit() {
        try {
            connection.commit();
        } catch (SQLException e) {
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            ConnectionInstance.getInstance().revertConnection(connection);
        }
    }

    @Override
    public Connection getConnection() {
        try {
            return ConnectionInstance.getInstance().getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
